package com.dongnao.network.nio_hashcat;

import java.io.IOException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.Set;

/**
 * @author sjy
 * @date 2024年05月12日 15:01
 */
public abstract class ReactorThread extends Thread {
    Selector selector;
    volatile boolean running = false;

    public ReactorThread() throws IOException {
        selector = Selector.open();
    }

    @Override
    public void run() {
        while (running) {
            try {
                selector.select();
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iter = selectionKeys.iterator();
                while (iter.hasNext()) {
                    SelectionKey key = iter.next();
                    //iter.remove();
                    int readyOps = key.readyOps();
                    if ((readyOps & (SelectionKey.OP_ACCEPT | SelectionKey.OP_READ)) != 0 || readyOps == 0) {
                        SelectableChannel channel = (SelectableChannel) key.attachment();
                        channel.configureBlocking(false);
                        dispatch(channel);
                        if (!channel.isOpen()) {
                            key.cancel();
                        }
                    }
                }
                selectionKeys.clear();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    abstract void dispatch(SelectableChannel channel) throws IOException;

    SelectionKey register(SelectableChannel channel) throws ClosedChannelException {
        SelectionKey selectionKey = channel.register(selector, 0, channel);
        return selectionKey;
    }

    void doStart() {
        if (!running) {
            running = true;
        }
        start();
    }

    void close() {
        running = false;
    }
}
